﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ayxjDllClass
{
    /// <summary>
    /// 调用多校验方法
    /// </summary>
    public delegate byte[] checkMethod(byte[] buffer, int start, int len);////定义委托，它定义了可以代表的方法的类型
    /// <summary>
    /// 数据校验
    /// </summary>
    public class dataVerification
    {
        #region 从汉字转换到16进制
        /// <summary>
        /// 从汉字转换到16进制
        /// </summary>
        /// <param name="txt">汉字</param>
        /// <param name="charset">编码,如"utf-8","gb2312"</param>
        /// <param name="fenge"></param>
        /// <returns>16进制字符串</returns>
        public static string ToHex(string txt, string charset, bool fenge)
        {
            if ((txt.Length % 2) != 0)
            {
                txt += " ";//空格
                //throw new ArgumentException("s is not valid chinese string!");
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            byte[] bytes = chs.GetBytes(txt);
            string str = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);
                if (fenge && (i != bytes.Length - 1))
                {
                    str += string.Format("{0}", ",");
                }
            }
            return str.ToLower();
        }
        #endregion
        #region 从16进制转换成汉字
        /// <summary>
        /// 从16进制转换成汉字
        /// </summary>
        /// <param name="hex">16进制</param>
        /// <param name="charset">编码,如"utf-8","gb2312"</param>
        /// <returns>汉字</returns>
        public static string UnHex(string hex, string charset)
        {
            if (hex == null)
                throw new ArgumentNullException("hex");
            hex = hex.Replace(",", "");
            hex = hex.Replace("\n", "");
            hex = hex.Replace("\\", "");
            hex = hex.Replace(" ", "");
            if (hex.Length % 2 != 0)
            {
                hex += "20";//空格
            }
            // 需要将 hex 转换成 byte 数组。 
            byte[] bytes = new byte[hex.Length / 2];

            for (int i = 0; i < bytes.Length; i++)
            {
                try
                {
                    // 每两个字符是一个 byte。 
                    bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
                    System.Globalization.NumberStyles.HexNumber);
                }
                catch
                {
                    // Rethrow an exception with custom message. 
                    throw new ArgumentException("hex is not a valid hex number!", "hex");
                }
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
            return chs.GetString(bytes);
        }
        #endregion

        #region 字符串转16进制字节数组
        /// <summary>
        /// 字符串转16进制字节数组
        /// </summary>
        /// <param name="hexString">字符串</param>
        /// <returns>6进制字节数组</returns>
        public static byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
            {
                string mo = hexString.Substring(hexString.Length - 1);
                hexString.Remove(hexString.Length - 1);
                hexString += ("0" + mo);
            }
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }
        #endregion

        #region 字节数组转16进制字符串
        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>16进制字符串</returns>
        public static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }
        #endregion
        #region 调用多校验方法
        /// <summary>
        /// 调用多校验方法
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-4/ITU    x4+x+1
        /// Poly: 0x03
        /// Init: 0x00
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验字符串</param>
        /// <param name="dataType">校验数据类型(0为16进制;1为ASCII码)</param>
        /// <param name="dataTop">返回校验数组是否高位在前</param>
        /// <param name="way">需调用的校验方法</param>
        /// <returns>返回校验码字节数组</returns>
        public static string allVerification(string buffer, Int16 dataType, bool dataTop, checkMethod way)
        {
            string ret = "";
            if (dataType == 0)
            {
                byte[] buf = dataVerification.strToToHexByte(buffer);
                byte[] data16 = way(buf, 0, buf.Length);
                if (dataTop == true)
                {
                    Array.Reverse(data16);//高低位互换
                    ret = byteToHexStr(data16);
                }
                else
                {
                    ret = byteToHexStr(data16);
                }
            }
            else
            {
                byte[] byteArray = Encoding.Default.GetBytes(buffer);
                byte[] dataAs = way(byteArray, 0, byteArray.Length);
                if (dataTop == true)
                {
                    Array.Reverse(dataAs);
                    ret = byteToHexStr(dataAs);
                }
                else
                {
                    ret = byteToHexStr(dataAs);
                }
            }
            return ret;
        }
        #endregion
       
     
       
        // **********************************************************************
        //CRC即循环冗余校验码（Cyclic Redundancy Check）：是数据通信领域中最常用的一种查错校验码，其特征是信息字段和校验字段的长度可以任意选定。
        //循环冗余检查（CRC）是一种数据传输检错功能，对数据进行多项式计算，并将得到的结果附在帧的后面，接收设备也执行类似的算法，以保证数据传输的正确性和完整性。 
        // CRC算法参数模型解释： 
        // NAME：参数模型名称。 
        //WIDTH：宽度，即CRC比特数。 
        // POLY：生成项的简写，以16进制表示。例如：CRC-32即是0x04C11DB7，忽略了最高位的"1"，即完整的生成项是0x104C11DB7。 
        //INIT：这是算法开始时寄存器（crc）的初始化预置值，十六进制表示。 
        //REFIN：待测数据的每个字节是否按位反转，True或False。 
        // REFOUT：在计算后之后，异或输出之前，整个数据是否按位反转，True或False。 
        // XOROUT：计算结果与此参数异或后得到最终的CRC值。
        // **********************************************************************
        #region CRC-4/ITU校验
        /// <summary>
        /// CRC-4/ITU校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-4/ITU    x4+x+1
        /// Poly: 0x03
        /// Init: 0x00
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC4_ITU(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0;// Initial value 
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0x0C);//0x0C = (reverse 0x03)>>(8-4)
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC-5/EPC校验
        /// <summary>
        /// CRC-5/EPC校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-5/EPC    x5+x3+1
        /// Poly: 0x09
        /// Init: 0x09
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC5_EPC(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint crc = 0x48;// Initial value: 0x48 = 0x09<<(8-5)
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x80) > 0)
                        crc = (uint)((crc << 1) ^ 0x48);// 0x48 = 0x09<<(8-5)
                    else
                        crc = (uint)(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc >> 3);
            return new byte[] { Convert.ToByte(Convert.ToString(ret[0], 2).Substring(3), 2) };
        }
        #endregion
        #region CRC-5/ITU校验
        /// <summary>
        /// CRC-5/ITU校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-5/ITU    x5+x4+x2+1
        /// Poly: 0x15
        /// Init: 0x00
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC5_ITU(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0x15);// 0x15 = (reverse 0x15)>>(8-5)
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC-5/USB校验
        /// <summary>
        /// CRC-5/USB校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-5/USB    x5+x2+1
        /// Poly: 0x05
        /// Init: 0x1F
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x1F    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC5_USB(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0x1F;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0x14);// 0x14 = (reverse 0x05)>>(8-5)
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { (byte)(crc ^ 0x1F) };
        }
        #endregion
        #region CRC-6/ITU校验
        /// <summary>
        /// CRC-6/ITU校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-6/ITU    x6+x+1
        /// Poly: 0x03
        /// Init: 0x00
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC6_ITU(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0x30);// 0x30 = (reverse 0x03)>>(8-6)
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC-7/MMC校验
        /// <summary>
        /// CRC-7/MMC校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-7/MMC    x7+x3+1
        /// Poly: 0x09
        /// Init: 0x00
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC7_MMC(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x80) > 0)
                        crc = (uint)((crc << 1) ^ 0x12);// 0x12 = 0x09<<(8-7)
                    else
                        crc = (uint)(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc >> 1);
           return new byte[] { Convert.ToByte(Convert.ToString(ret[0], 2).Substring(1), 2) };
        }
       
        #endregion
        #region CRC8校验
        /// <summary>
        /// CRC8校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC8    x8+x2+x+1
        /// Poly: 0x07
        /// Init: 0x00
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC8(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            UInt64 crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x80) > 0)
                        crc = (UInt64)((crc << 1) ^ 0x07);
                    else
                        crc = (UInt64)(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            return new byte[] { ret[0] };
        }
        #endregion
        #region CRC-8/ITU校验
        /// <summary>
        /// CRC-8/ITU校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-8/ITU    x8+x2+x+1
        /// Poly: 0x07
        /// Init: 0x00
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x55    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC8_ITU(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            UInt64 crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x80) > 0)
                        crc = (UInt64)((crc << 1) ^ 0x07);
                    else
                        crc = (UInt64)(crc << 1);
                }
            }

            byte[] ret = BitConverter.GetBytes(crc ^ 0x55);
            return new byte[] { ret[0] };
        }
        #endregion
        #region CRC-8/MAXIM校验
        /// <summary>
        /// CRC-8/MAXIM校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-8/MAXIM    x8+x5+x4+1
        /// Poly: 0x31
        /// Init: 0x00
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC8_MAXIM(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0x8C);// 0x8C = reverse 0x31 
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC-8/ROHC校验
        /// <summary>
        /// CRC-8/ROHC校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-8/ROHC    x8+x2+x+1
        /// Poly: 0x07
        /// Init: 0xFF
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x00    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC8_ROHC(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            byte crc = 0xFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (byte)((crc >> 1) ^ 0xE0);// 0xE0 = reverse 0x07
                    else
                        crc = (byte)(crc >> 1);
                }
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC8_Z1校验
        static byte[] table = { 0x00, 0x1C, 0x38, 0x24, 0x70, 0x6C, 0x48, 0x54, 0xE0, 0xFC,
                                0xD8, 0xC4, 0x90, 0x8C, 0xA8, 0xB4, 0xDC, 0xC0, 0xE4, 0xF8,
                                0xAC, 0xB0, 0x94, 0x88, 0x3C, 0x20, 0x04, 0x18, 0x4C, 0x50,
                                0x74, 0x68, 0xA4, 0xB8, 0x9C, 0x80, 0xD4, 0xC8, 0xEC, 0xF0,
                                0x44, 0x58, 0x7C, 0x60, 0x34, 0x28, 0x0C, 0x10, 0x78, 0x64,
                                0x40, 0x5C, 0x08, 0x14, 0x30, 0x2C, 0x98, 0x84, 0xA0, 0xBC,
                                0xE8, 0xF4, 0xD0, 0xCC, 0x54, 0x48, 0x6C, 0x70, 0x24, 0x38,
                                0x1C, 0x00, 0xB4, 0xA8, 0x8C, 0x90, 0xC4, 0xD8, 0xFC, 0xE0,
                                0x88, 0x94, 0xB0, 0xAC, 0xF8, 0xE4, 0xC0, 0xDC, 0x68, 0x74,
                                0x50, 0x4C, 0x18, 0x04, 0x20, 0x3C, 0xF0, 0xEC, 0xC8, 0xD4,
                                0x80, 0x9C, 0xB8, 0xA4, 0x10, 0x0C, 0x28, 0x34, 0x60, 0x7C,
                                0x58, 0x44, 0x2C, 0x30, 0x14, 0x08, 0x5C, 0x40, 0x64, 0x78,
                                0xCC, 0xD0, 0xF4, 0xE8, 0xBC, 0xA0, 0x84, 0x98, 0xA8, 0xB4,
                                0x90, 0x8C, 0xD8, 0xC4, 0xE0, 0xFC, 0x48, 0x54, 0x70, 0x6C,
                                0x38, 0x24, 0x00, 0x1C, 0x74, 0x68, 0x4C, 0x50, 0x04, 0x18,
                                0x3C, 0x20, 0x94, 0x88, 0xAC, 0xB0, 0xE4, 0xF8, 0xDC, 0xC0,
                                0x0C, 0x10, 0x34, 0x28, 0x7C, 0x60, 0x44, 0x58, 0xEC, 0xF0,
                                0xD4, 0xC8, 0x9C, 0x80, 0xA4, 0xB8, 0xD0, 0xCC, 0xE8, 0xF4,
                                0xA0, 0xBC, 0x98, 0x84, 0x30, 0x2C, 0x08, 0x14, 0x40, 0x5C,
                                0x78, 0x64, 0xFC, 0xE0, 0xC4, 0xD8, 0x8C, 0x90, 0xB4, 0xA8,
                                0x1C, 0x00, 0x24, 0x38, 0x6C, 0x70, 0x54, 0x48, 0x20, 0x3C,
                                0x18, 0x04, 0x50, 0x4C, 0x68, 0x74, 0xC0, 0xDC, 0xF8, 0xE4,
                                0xB0, 0xAC, 0x88, 0x94, 0x58, 0x44, 0x60, 0x7C, 0x28, 0x34,
                                0x10, 0x0C, 0xB8, 0xA4, 0x80, 0x9C, 0xC8, 0xD4, 0xF0, 0xEC,
                                0x84, 0x98, 0xBC, 0xA0, 0xF4, 0xE8, 0xCC, 0xD0, 0x64, 0x78,
                                0x5C, 0x40, 0x14, 0x08, 0x2C, 0x30 };
        /// <summary>
        /// CRC8_Z1协议校验
        /// </summary>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC8_Z1(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            int i;
            byte crc = 0x00;
            int tableIndex;
            for (i = start; i < length; i++)
            {
                tableIndex = crc ^ (buffer[i] & 0xFF);
                crc = table[tableIndex];
            }
            return new byte[] { crc };
        }
        #endregion
        #region CRC-12校验
        /// <summary>
        /// CRC-12校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-12    x16+x12+x5+1
        /// Poly: 0x80
        /// Init: 0x0000
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x0000   
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC12(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0;// Initial value
            short iQ = 0, iR = 0;
            for (int i = start; i < length; i++)
            {
                // 多项式除法
                // 如果该位为1
                if ((buffer[i] & (0x80 >> iR)) > 0)
                {
                    // 则在余数尾部添1否则添0
                    crc |= 0x01;
                }
                // 如果12位除数中的最高位为1，则够除
                if (crc >= 0x1000)
                {
                    crc ^= 0x180D;
                }
                crc <<= 1;
                iR++;
                if (8 == iR)
                {
                    iR = 0;
                    iQ++;
                }
            }
            // 对后面添加的12个0做处理
            for (int i = 0; i < 12; i++)
            {
                if (crc >= 0x1000)
                {
                    crc ^= 0x180D;
                }
                crc <<= 1;
            }
            crc >>= 1;
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }
        #endregion
        #region CRC-16/CCITT校验
        /// <summary>
        /// CRC-16/CCITT校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/CCITT    x16+x12+x5+1
        /// Poly: 0x1021
        /// Init: 0x0000
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x0000   
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_CCITT(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0x8408);// 0x8408 = reverse 0x1021
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            return ret;
        }
        #endregion
        #region CRC-16/CCITT FALSE校验
        /// <summary>
        /// CRC-16/CCITT FALSE校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/CCITT FALSE    x16+x12+x5+1
        /// Poly: 0x1021
        /// Init: 0xFFFF
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x0000    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_CCITT_FALSE(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= (uint)(buffer[i] << 8);
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x8000) > 0)
                        crc = (uint)((crc << 1) ^ 0x1021);
                    else
                        crc = (uint)(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
        #endregion
        #region CRC-16/DNP校验
        /// <summary>
        /// CRC-16/DNP校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/DNP    x16+x13+x12+x11+x10+x8+x6+x5+x2+1
        /// Poly: 0x3D65
        /// Init: 0x0000
        /// Refin: true
        /// Refout: true
        /// Xorout: 0xFFFF    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_DNP(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA6BC);// 0xA6BC = reverse 0x3D65
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(0xffff ^ crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
        #endregion
        #region CRC-16/IBM校验
        /// <summary>
        /// CRC-16/IBM校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/IBM    x16+x15+x2+1
        /// Poly: 0x8005
        /// Init: 0x0000
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x0000    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_IBM(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            return ret;
        }
        #endregion
        #region CRC-16/MAXIM校验
        /// <summary>
        /// CRC-16/MAXIM校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/MAXIM    x16+x15+x2+1
        /// Poly: 0x8005
        /// Init: 0x0000
        /// Refin: true
        /// Refout: true
        /// Xorout: 0xFFFF    
        ///*************************************************************************
        /// </remarks>/// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_MAXIM(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005 
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(0xffff^crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
        #endregion
        #region CRC-16/MODBUS校验
        /// <summary>
        /// CRC-16/MODBUS校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/MODBUS    x16+x15+x2+1
        /// Poly: 0x8005
        /// Init: 0xFFFF
        /// Refin: true
        /// Refout: true
        /// Xorout: 0x0000    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_MODBUS(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005 
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            return ret;
        }
        #endregion
        #region CRC-16/USB校验
        /// <summary>
        /// CRC-16/USB校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/USB    x16+x15+x2+1
        /// Poly: 0x8005
        /// Init: 0xFFFF
        /// Refin: true
        /// Refout: true
        /// Xorout: 0xFFFF    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_USB(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = Convert.ToUInt16(((crc >> 1) ^ 0xA001));// 0x8408 = reverse 0x1021
                    else
                        crc = Convert.ToUInt16((crc >> 1));
                }
            }
            byte[] ret = BitConverter.GetBytes(0xffff ^ crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
        #endregion
        #region CRC-16/X25校验
        /// <summary>
        /// CRC-16/X25校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/X25    x16+x12+x5+1 
        /// Poly: 0x1021
        /// Init: 0xFFFF
        /// Refin: true
        /// Refout: true
        /// Xorout: 0xFFFF    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_X25(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = Convert.ToUInt16(((crc >> 1) ^ 0x8408));// 0x8408 = reverse 0x1021
                    else
                        crc = Convert.ToUInt16((crc >> 1));
                }
            }
            byte[] ret = BitConverter.GetBytes(0xffff^crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
        #endregion
        #region CRC-16/XMODEM校验
        /// <summary>
        /// CRC-16/XMODEM校验 
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC-16/XMODEM    x16+x12+x5+1 
        /// Poly: 0x1021
        /// Init: 0x0000
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x0000    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC16_XMODEM(byte[] buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint crc = 0;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= (uint)(buffer[i] << 8);
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x8000) > 0)
                        crc = (uint)((crc << 1) ^ 0x1021);//0x8408 = reverse 0x1021
                    else
                        crc = (uint)(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            if (ret.Length > 2) { ret = new byte[2] { ret[0], ret[1] }; }
            return ret;
        }
     
        #endregion
        #region CRC32校验
        /// <summary>
        /// CRC32校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC32    x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
        /// Poly: 0x04C11DB7
        /// Init: 0xFFFFFFFF
        /// Refin: true
        /// Refout: true
        /// Xorout: 0xFFFFFFFF    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC32(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint crc = 0xFFFFFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
                    else
                        crc = crc >> 1;
                }
            }
            byte[] ret = BitConverter.GetBytes(~crc);
            return ret;
        }
        #endregion
        #region CRC32/MPEG-2校验
        /// <summary>
        /// CRC32/MPEG-2校验
        /// </summary>
        /// <remarks>
        /// **********************************************************************
        /// Name: CRC32/MPEG-2    x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
        /// Poly: 0x04C11DB7
        /// Init: 0xFFFFFFFF
        /// Refin: false
        /// Refout: false
        /// Xorout: 0x00000000    
        ///*************************************************************************
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] CRC32_MPEG2(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            UInt64 crc = 0xFFFFFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= (Convert.ToUInt64(buffer[i]) << 24);
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x80000000) > 0)
                        crc = Convert.ToUInt64((crc << 1) ^ 0x04C11DB7);
                    else
                        crc = Convert.ToUInt64(crc << 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            if (ret.Length > 4) { ret = new byte[4] { ret[0], ret[1], ret[2], ret[3] }; }
            return ret;
        }
       
        #endregion
        #region LRC(纵向冗余校验)
        /// **********************************************************************
        /// 纵向冗余校验（Longitudinal Redundancy Check，简称：LRC）是通信中常用的一种校验形式，也称LRC校验或纵向校验。
        /// 它是一种从纵向通道上的特定比特串产生校验比特的错误检测方法。在行列格式中（如磁带），LRC经常是与VRC一起使用，这样就会为每个字符校验码。
        /// 在工业领域Modbus协议Ascii模式采用该算法。 
        /// LRC计算校验码,具体算法如下： 
        /// 1、对需要校验的数据（2n个字符）两两组成一个16进制的数值求和。 
        /// 2、将求和结果与256求模。 
        /// 3、用256减去所得模值得到校验结果（另一种方法：将模值按位取反然后加1）。
        ///*************************************************************************  
        /// <summary>
        /// LRC(纵向冗余校验)
        /// </summary>
        /// <remarks>
        /// 具体算法如下： 
        /// 1、对需要校验的数据（2n个字符）两两组成一个16进制的数值求和。 
        /// 2、将求和结果与256求模。 
        /// 3、用256减去所得模值得到校验结果（另一种方法：将模值按位取反然后加1）。
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] Lrc(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint lrc = 0;// Initial value
            for (int i = start; i < len; i++)
            {
                lrc += buffer[i];
            }
            lrc = (uint)((lrc ^ 0xFF) + 1);
            byte[] ret = BitConverter.GetBytes(lrc);
            return new byte[] { ret[0] };
        }
        #endregion
        #region BCC(异或校验)
        /// **********************************************************************
        ///BCC(Block Check Character/信息组校验码)，因校验码是将所有数据异或得出，故俗称异或校验。
        ///具体算法是：将每一个字节的数据（一般是两个16进制的字符）进行异或后即得到校验码。
        /// **********************************************************************
        /// <summary>
        /// BCC(异或校验)
        /// </summary>
        /// <remarks>
        /// 具体算法是：将每一个字节的数据（一般是两个16进制的字符）进行异或后即得到校验码。
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] Bcc(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            uint bcc = 0;// Initial value
            for (int i = start; i < len; i++)
            {
                bcc ^= buffer[i];
            }
            byte[] ret = BitConverter.GetBytes(bcc);
            return new byte[] { ret[0] };
        }
        #endregion
        #region ADD累加和校验
        /// <summary>
        /// ADD(累加和校验)
        /// </summary>
        /// <remarks>
        /// 一串数据的累加和，即数据相加后的模255的值
        /// </remarks>
        /// <param name="buffer">被校验的字节数组</param>
        /// <param name="start">起始位置</param>
        /// <param name="len">字节长度</param>
        /// <returns>返回校验码字节数组</returns>
        public static byte[] allAdd(byte[] buffer, int start, int len)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            int num = 0;
            //所有字节累加
            for (int i = start; i < len; i++)
            {
                num = (num + buffer[i]) % 0xFFFF;
            }
            byte[] ret = BitConverter.GetBytes(num);
            return ret;
        }
        #endregion
    }
}
